﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.IO;
using System.Text;
using System.Threading;
using System.Windows.Forms;
using System.Text.RegularExpressions;
using System.Drawing;
using System.Security.Cryptography;

namespace QQFriendList
{
    public partial class Form1 : Form
    {
        private string SID = "";
        private string HOST = "";
        private string URL_ADDR = "";
        private string URL_EXIT = "";

        private string MYACCOUNT = "";
        private string MYPASSWORD = "";

        private bool login = false;
        private bool getSidAndHost = false;
        private bool getContactsUrl = false;
        private bool getFriensList = false;
        private bool logout = false;

        public struct Friend
        {
            public string number;
            public string name;
        }
        List<Friend> FRIENDLIST = new List<Friend>();

        private delegate void FlushClient(); //代理
        Thread thread = null;


        public Form1()
        {
            InitializeComponent();
        }
        private void Form1_Load(object sender, EventArgs e)
        {

            button_ImportList.Enabled = false;
            ZHUCE.REGISTERED = ZHUCE.Judge_Whether_Registered();
            if (ZHUCE.REGISTERED)
            {
                ZHUCE.VisitCount = 10000000;
                RegeToolStripMenuItem.Text = "关于";
                RegeToolStripMenuItem.ForeColor = System.Drawing.Color.Black;
            }
            else
            {
                ZHUCE.VisitCount = 10;
            }
        }

        #region webbrowser
        private void webBrowser1_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
        {
            //logger_list(this.webBrowser1.Url.ToString());           //记录
            urlComboBox.Text = this.webBrowser1.Url.AbsoluteUri;    //地址栏
            //this.Text = webBrowser1.DocumentTitle;                  //标量
        }
        private void webBrowser1_NewWindow(object sender, CancelEventArgs e)
        {
            e.Cancel = true;
        }
        #endregion

        #region thread
        private void CrossThreadFlush()
        {
            while (true)
            {
                Random randomNumber = new Random();
                Thread.Sleep(randomNumber.Next(3000, 6000));
                ThreadFunction();
            }
        }
        private void ThreadFunction()
        {
            if (this.dataGridView_QQFriendList.InvokeRequired || this.listBox1.InvokeRequired)//等待异步
            {
                FlushClient fc = new FlushClient(ThreadFunction);
                this.Invoke(fc); //通过代理调用刷新方法
            }
            else
            {
                if (!login)
                {
                    login = startLogin();
                    if (!login)
                    {
                        startLogout();
                    }
                }
                else if (!getContactsUrl)
                {
                    getContactsUrl = checkLoginANDpickUpContactsUrl(this.webBrowser1);
                    if (getContactsUrl)
                    {
                        string contactsUrl = "http://" + HOST + URL_ADDR;
                        this.webBrowser1.Navigate(contactsUrl.Replace("&amp;", "&"));
                    }
                }
                else if (!getFriensList)
                {
                    getFriensList = pickUpQQFriendList(this.webBrowser1);
                    if (getFriensList)
                    {
                        startLogout();
                    }
                }
                else if (!logout)
                {
                    logout = checkLogout();
                }
            }
        }
        #endregion

        #region record
        private void logger_list(string content)
        {
            DateTime currentTime = DateTime.Now;
            string current_record = currentTime.ToString("T") + " " + content;
            listBox1.Items.Add(current_record);
            listBox1.TopIndex = this.listBox1.Items.Count - (int)(this.listBox1.Height / this.listBox1.ItemHeight);
        }
        private void logger_file(string content)
        {
            string fname = "logfile.txt";
            FileInfo finfo = new FileInfo(fname);
            if (finfo.Exists && finfo.Length > 512000)
            {
                finfo.Delete();
            }
            using (FileStream fs = finfo.OpenWrite())
            {
                DateTime currentTime = DateTime.Now;
                string current_record = currentTime.ToString("T") + " " + content;
                StreamWriter w = new StreamWriter(fs);
                w.BaseStream.Seek(0, SeekOrigin.End);//设置写数据流的起始位置为文件流的末尾  
                w.Write(current_record + "\r\n");  //写入日志内容并换行  
                w.Flush();
                w.Close();  //关闭写数据流  
            }
        }
        private void logger_all(string log)
        {
            logger_list(log);
            logger_file(log);
        }
        #endregion

        #region regedit
        private void RegeToolStripMenuItem_Click(object sender, EventArgs e)
        {
            AboutBox1 aboutBox = new AboutBox1();
            aboutBox.ShowDialog();
        }
        #endregion

        #region getQFriendList
        private void button_Start_Click(object sender, EventArgs e)
        {


            login = false;
            getSidAndHost = false;
            getContactsUrl = false;
            getFriensList = false;
            logout = false;
            FRIENDLIST.Clear();
            dataGridView_QQFriendList.Rows.Clear();

            MYACCOUNT = textBox_Account.Text;
            MYPASSWORD = textBox_Password.Text;

            if (MYACCOUNT == "" || MYPASSWORD == "")
            {
                MessageBox.Show("用户名或密码不能为空！", "系统提示", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                return;
            }

            logger_list("开始与服务器通讯");
            string qzoneurl = "http://wap.mail.qq.com/";
            webBrowser1.Navigate(qzoneurl);
            this.button_Start.Enabled = false;

            thread = new Thread(CrossThreadFlush);
            thread.IsBackground = true;
            thread.Start();
        }
        private bool startLogin()
        {
            logger_list("开始查找登录入口");
            HtmlElement uin = webBrowser1.Document.All["uin"];
            HtmlElement type = webBrowser1.Document.All["aliastype"];
            HtmlElement pwd = webBrowser1.Document.All["pwd"];
            HtmlElement btlogin = webBrowser1.Document.All["btlogin"];  //name="btlogin" class="btn1" id="submitBtn"
            if (uin == null || type == null || pwd == null || btlogin == null)
            {
                logger_list("无法找到登录入口");
                return false;
            }
            else
            {
                //uin.SetAttribute("value", "118134555");
                uin.InnerText = MYACCOUNT; //设置网页元素的另一种方法
                type.SetAttribute("value", "qq.com");
                pwd.SetAttribute("value", MYPASSWORD);
                btlogin.InvokeMember("click");
                logger_list("开始尝试登录");
                return true;
            }
        }
        private bool pickUpSidAndHost(Uri url, out string host, out string sid)
        {
            logger_list("开始协商通讯参数");
            string regSID = "sid=(.+?)&";
            host = url.Host;
            if (url.AbsoluteUri.Contains("today") && url.AbsoluteUri.Contains("sid"))
            {
                Match matchSid = Regex.Match(url.AbsoluteUri, regSID);
                sid = matchSid.Groups[1].ToString();
                if (sid != "" && host != "")
                {
                    logger_list("协商通讯参数成功");
                    return true;
                }
            }
            host = "";
            sid = "";
            logger_list("协商通讯参数失败");
            return false;
        }
        private bool checkLoginANDpickUpContactsUrl(WebBrowser myWebBrowser)
        {
            HtmlDocument elements = myWebBrowser.Document;
            //logger_list("开始校验登录");
            if (myWebBrowser.Url.ToString().Contains("errtype"))
            {
                logger_list("登录失败！用户名或密码错误？");

                //失败后禁止再次尝试
                login = true;
                getSidAndHost = true;
                getContactsUrl = true;
                getFriensList = true;
                logout = true;

                return true;
            }

            getSidAndHost = pickUpSidAndHost(this.webBrowser1.Url, out HOST, out SID);
            if (!getSidAndHost)
            {
                return false;
            }

            logger_list("登录成功");
            login = true;
            logger_list("开始启动获取请求");
            
            foreach (HtmlElement em in elements.All) 
            {
                string str = em.Name;
                string id = em.Id;
                string htmlinner = em.InnerHtml;
                string htmlouter = em.OuterHtml;

                if ((htmlinner != null) && htmlinner.StartsWith("<A class=grid") && (htmlinner.Contains("addr_listall")))
                {
                    string[] gridObjectList = Regex.Split(htmlinner, "class=grid ", RegexOptions.IgnoreCase);
                    for (int i = 0; i < gridObjectList.Length; i++)
                    {
                        //logger_list(gridObjectList[i]);
                        Match UrlPath = Regex.Match(gridObjectList[i], "href=\"(.+?)\"");
                        if (gridObjectList[i].Contains("addr_listall") && UrlPath.Success)
                        {
                            URL_ADDR = UrlPath.Groups[1].ToString();
                            logger_list("启动获取请求成功");
                            return true;
                        }
                    }
                }
            }
            logger_list("启动获取请求失败!");
            return false;
            
        }
        private bool pickUpQQFriendList(WebBrowser myWebBrowser)
        {
            logger_list("开始获取好友列表");
            HtmlDocument elements = webBrowser1.Document;
            foreach (HtmlElement em in elements.All) //轮循
            {
                
                string str = em.Name;
                string id = em.Id;
                string htmlinner = em.InnerHtml;
                string htmlouter = em.OuterHtml;

                if ((htmlinner != null)
                    && htmlinner.StartsWith("<DIV class=\"mui_nowrap")
                    && htmlinner.Contains("m_title")
                    && htmlinner.Contains("m_summary")
                    && htmlinner.Contains("@qq.com"))
                {
                    Match qqNumber = Regex.Match(htmlinner, "<DIV\\s+class=\".+?m_summary\">(\\d{5,10})@qq\\.com</DIV>");
                    Match qqName = Regex.Match(htmlinner, "<A\\s+href=\".+?\">(.+?)</A></DIV>");
                    if (qqNumber.Success && qqName.Success)
                    {
                        Friend qfItem = new Friend();
                        qfItem.number = qqNumber.Groups[1].ToString();
                        qfItem.name = qqName.Groups[1].ToString();
                        FRIENDLIST.Add(qfItem);
                    }
                }
            }
            if (FRIENDLIST.Count > 0)
            {
                insertFriendToList();
                logger_list("共获取到 " + FRIENDLIST.Count.ToString() + " 个好友");
                //button_Start.Visible = false;
                button_ImportList.Enabled = true;
                return true;
            }
            else
            {
                logger_list("获取到 0 个好友！？");
                logger_list("如果你QQ中有好友，但却没有获取到，请与软件作者联系！");
                return false;
            }
        }
        private void startLogout()
        {
            getSidAndHost = pickUpSidAndHost(this.webBrowser1.Url, out HOST, out SID);
            if (!getSidAndHost)
            {
                logger_list("无法全身而退！？"); ;
            }
            URL_EXIT = "/cgi-bin/logout?sid=" + SID;
            string exitUrl = "http://" + HOST + URL_EXIT;
            logger_list("开始退出");
            this.webBrowser1.Navigate(exitUrl);
        }
        private bool checkLogout()
        {
            if (this.webBrowser1.Url.ToString().Contains("logout") && this.webBrowser1.Url.ToString().Contains("loginpage"))
            {
                logger_list("退出成功");
                return true;
            }
            return false;
        }
        private void insertFriendToList()
        {
            for (int i = 0; i < FRIENDLIST.Count; i++)
            {
                DataGridViewRow row_friend = new DataGridViewRow();
                DataGridViewTextBoxCell cell_number = new DataGridViewTextBoxCell();
                cell_number.Value = FRIENDLIST[i].number;
                row_friend.Cells.Add(cell_number);

                DataGridViewTextBoxCell cell_name = new DataGridViewTextBoxCell();
                cell_name.Value = FRIENDLIST[i].name;
                row_friend.Cells.Add(cell_name);

                string tabNumber = (FRIENDLIST[i].number.ToString().Length < 9) ? ("\t\t") : ("\t");
                //logger_list("QQ号码: " + FRIENDLIST[i].number + tabNumber + "备注姓名: " + FRIENDLIST[i].name);

                dataGridView_QQFriendList.Rows.Add(row_friend);
            }
        }

        private void button_ImportList_Click(object sender, EventArgs e)
        {
            string fname = "qqfriend.txt";
            FileInfo finfo = new FileInfo(fname);
            if (finfo.Exists)
            {
                finfo.Delete();
            }

            for (int i = 0; i < FRIENDLIST.Count; i++)
            {
                if (!ZHUCE.REGISTERED && i > 10)
                {
                    break;
                }
                else
                {
                    string tabNumber = (FRIENDLIST[i].number.ToString().Length < 8) ? ("\t\t") : ("\t");
                    string content = "QQ号码: " + FRIENDLIST[i].number + tabNumber + "备注姓名: " + FRIENDLIST[i].name;
                    using (FileStream fs = finfo.OpenWrite())
                    {
                        StreamWriter w = new StreamWriter(fs);
                        w.BaseStream.Seek(0, SeekOrigin.End);//设置写数据流的起始位置为文件流的末尾
                        if (i == 0)
                        {
                            DateTime currentTime = DateTime.Now;
                            if (ZHUCE.REGISTERED)
                            {
                                content = currentTime.ToString("G") + "\r\n\r\nQQ号码" + textBox_Account.Text + "的好友列表如下：\r\n===================\r\n" + content;
                            }
                            else
                            {
                                content = currentTime.ToString("G") + "\r\n未注册版本，最多导出10条\r\nQQ号码" + textBox_Account.Text + "的好友列表如下：\r\n===================\r\n" + content;
                            }
                            
                        }
                        w.Write(content + "\r\n");  //写入日志内容并换行  
                        w.Flush();
                        w.Close();  //关闭写数据流  
                    }
                }
            }

            System.Diagnostics.Process.Start("notepad.exe", "qqfriend.txt");
            button_ImportList.Enabled = false;

        }
        #endregion

        private void dataGridView_QQFriendList_RowPostPaint(object sender, DataGridViewRowPostPaintEventArgs e)
        {
            DataGridView dw = (DataGridView)sender;
            Rectangle rectangle = new Rectangle(e.RowBounds.Location.X, e.RowBounds.Location.Y, dw.RowHeadersWidth - 4, e.RowBounds.Height);
            TextRenderer.DrawText(e.Graphics, (e.RowIndex + 1).ToString(),
            dw.RowHeadersDefaultCellStyle.Font,rectangle,
            dw.RowHeadersDefaultCellStyle.ForeColor,
            TextFormatFlags.VerticalCenter | TextFormatFlags.Right);
        }


    }
}
